import json
import datetime
import requests
import aiohttp
import asyncio

from aiohttp import ClientSession
from fastapi import HTTPException
from starlette import status

from models.CardPool import CardPool
from models.base import Cards


class ArkNight:
    # https://as.hypergryph.com/user/auth/v1/token_by_phone_password

    def __init__(self, token):

        self.head = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68"
        }
        self.token = token
        # 存所有抽的列表
        self.list_datas = []
        # 返回的数据是否为空
        self.flag = False
        self.status_error = False
        self.user_id = ""

    def login(self, phone, password):
        url = "https://as.hypergryph.com/user/auth/v1/token_by_phone_password"
        data = {
            "phone": phone,
            "password": password
        }
        text_data = requests.post(url=url, data=data, headers=self.head).text
        data: json = json.loads(text_data)
        print(data)

    async def fetch_cards(self, session: ClientSession, page):

        params = {
            "page": page,
            "token": self.token
        }
        url = "https://ak.hypergryph.com/user/api/inquiry/gacha"
        async with session.get(url, verify_ssl=False, params=params, headers=self.head) as response:
            text = await response.text()
            data = json.loads(text)
            # print(data)
            if data["code"] != 0:
                self.status_error = True
                return
            data = data["data"]["list"]
            if len(data) == 0:
                self.flag = True
                return
            # 把每一条数据存到列表里面
            for line in data:
                self.list_datas.append(line)
            # print(f"得到结果--第{page}页")

    async def fetch_userid(self, session: ClientSession):
        url = "https://as.hypergryph.com/u8/user/info/v1/basic"
        dic_token = {"token": self.token}
        data = {
            "appId": 1,
            "channelMasterId": 1,
            "channelToken": dic_token
        }
        async with session.post(url, verify_ssl=False, data=json.dumps(data), headers=self.head) as response:
            text = await response.text()
            data = json.loads(text)
            try:
                if data['status'] != 0:
                    self.status_error = True
                    return
            except Exception:
                self.status_error = True
                return
            self.user_id = data['data']['uid']

    async def arequest(self, step=5):
        """
        异步请求发起函数
        每次请求5页，如果这5页包含空数据，就停止请求
        :return:
        """
        border = 1
        async with aiohttp.ClientSession() as session:
            while not self.flag and not self.status_error:
                tasks = [asyncio.create_task(self.fetch_cards(session, page_num)) for page_num in
                         range(border, border + step)]
                tasks.append(asyncio.create_task(self.fetch_userid(session)))
                await asyncio.wait(tasks)
                border += step
                if self.status_error:
                    raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="token 有误")

    async def parse_data(self) -> dict:
        pool_name_list = dict()
        if not self.user_id:
            return pool_name_list
        orders_list = sorted(self.list_datas, key=lambda x: x['ts'])
        await self.merge_data(orders_list)
        sql_list = await Cards.filter(user_id=self.user_id).order_by('create_time')

        for line in sql_list:
            pool_name = line.pool
            if pool_name not in pool_name_list:
                pool_name_list[pool_name] = CardPool(pool_name=pool_name)
            cardpool: CardPool = pool_name_list.get(pool_name)
            cardpool.data_process_obj(line)
        return pool_name_list

    async def merge_data(self, orders_list):
        if not self.user_id:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="user id 获取失败，重试")
        data: Cards = await Cards.filter(user_id=self.user_id).order_by('-create_time').first()

        if data is None:
            print("数据库no data，全部添加")
            for line in orders_list:
                await self.add_data_mysql(line)
        else:
            l = 0
            r = len(orders_list) - 1
            curr: datetime = data.create_time
            curr = curr.timestamp()
            if orders_list[0]['ts'] > curr:
                print("当前所有数据都不在数据库，全部添加")
                for line in orders_list:
                    await self.add_data_mysql(line)
                return
            res_index = -1
            while l <= r:
                mid = (l + r) // 2
                if curr > orders_list[mid]["ts"]:
                    l += 1
                elif curr < orders_list[mid]["ts"]:
                    r -= 1
                else:
                    res_index = mid
                    break
            if res_index == len(orders_list) - 1:
                print("数据库数据为最新")
            else:
                print("部分数据不存在")
                for index in range(res_index + 1, len(orders_list)):
                    line = orders_list[index]
                    await self.add_data_mysql(line)

    async def add_data_mysql(self, line: json):
        if not self.user_id:
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="user id 获取失败，重试")

        # 这里存json数据的时候，记着把json数据序列化成str再存，要不然加载的时候会出错
        await Cards.create(pool=line["pool"], create_time=line["ts"],
                           data=json.dumps(line['chars']), user_id=self.user_id)

    async def auto_process(self):

        await self.arequest()
        dic = await self.parse_data()
        # for key in dic.keys():
        #     print(dic.get(key))
        return dic
